#include "EventLoop.h"
#include <sys/eventfd.h>
#include <unistd.h>
#include <fcntl.h>
#include "Channel.h"
#include "Logger.h"
#include "Poller.h"
#include<memory>
// 防止一个线程创建多个EventLoop thread local
__thread EventLoop *t_loopInThisThread = nullptr;

// epoll的超时时间，这里是Poller的超时时间
const int kPollTimeMs = 10000;

// 创建wakeupfd，用来notify唤醒subReactor处理新来的channel
int createEventfd()
{
    int evtfd = ::eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
    if (evtfd < 0)
    {
        LOG_FATAL("eventfd error:%d \n", errno);
    }
    return evtfd;
}

using Functor = std::function<void>;

EventLoop::EventLoop()
    : looping_(false), quit_(false), callingPendingFunctors_(false), threadId_(CurrentThread::tid()), poller_(Poller::newDefaultPoller(this)), wakeupFd_(createEventfd()), wakeupChannel_(new Channel(this, wakeupFd_)), currentActiveChannel_(nullptr)
{
    LOG_DEBUG("EvetnLoop created %p in thread %d \n", this, threadId_);
    if (t_loopInThisThread)
    {
        LOG_FATAL("Another EventLoop %p exists in this thread %d \n", t_loopInThisThread, threadId_);
    }
    else
    {
        t_loopInThisThread = this;
    }
    // 设置wakeupFd的监听事件类型，以及发生事件后的回调方法
    wakeupChannel_->setReadCallback(std::bind(&EventLoop::handlerRead, this));
    // 每一个eventloop都将监听wakeupchannel的EPOLLIN读时间
    wakeupChannel_->enableReading();
}
EventLoop::~EventLoop()
{
    wakeupChannel_->disableAll();
    wakeupChannel_->remove();
    ::close(wakeupFd_);
    t_loopInThisThread = nullptr;
}

// 开启事件循环
void EventLoop::loop()
{
    looping_ = true;
    quit_ = false;

    LOG_INFO("EventLoop %p start looping \n",this);
    while(!quit_)
    {
        // 主要监听两类f，一种是client的fd（listen上来的），一种是wakeupfd（唤醒subloop的fd）
        activeChannels_.clear();
        pollReturntime_ = poller_->poll(kPollTimeMs,&activeChannels_);
        // 1.处理epoll_wait 上来的事件
        for(Channel* channel: activeChannels_)
        {
            // Poller 监听哪些channel发生时间了，然后上报给EventLoop，通知channel通知
            channel->handlerEvent(pollReturntime_);
        }
        // 执行当前EventLoop事件循环需要处理的回调操作
        /**
         * 2. 处理之前runInLoop或queueInLoop保存的就绪任务。
         * IO 线程 mainLoop accept| =》 fd channel 打包fd， channel得分配给subloop
         * mainLoop事先注册一个回调（需要subloop来执行）  wakeup subloop后，执行下面的cb操作
        */
        doPendingFunctors();
    }

    LOG_INFO("EventLoop %p stop looping. \n",this);
    looping_ = false;
    
}

// 退出事件循环 1.loop在自己的线程中 2. 非loop的线程中，调用loop的quit
// subloop1 退出 subloop2 不理解
void EventLoop::quit()
{
    quit_ = true;
    {
    if(!isInLoopThread()) // 如果是在其他线程中，调用quit； 在一个subloop（worker）中调用mainLoop的quit
        wakeup();
    }
}

// 把cb放到
//  在当前loop中执行cb,runInLoop包含queueInLoop
void EventLoop::runInLoop(Functor cb)
{
    if(isInLoopThread()) // 在当前的loop线程中，执行cb
    {
        cb();
    }
    else // 在非loop 线程中执行cb
    {
        queueInLoop(cb);
    }
}
// 把cb放入队列中，唤醒loop所在的线程，执行cb
void EventLoop::queueInLoop(Functor cb)
{
    {
        std::unique_lock<std::mutex> lock(mutex_);
        pendingFunctors_.emplace_back(cb);
    }
    // 唤醒相应的需要执行上面的回调操作的loop线程
    // || callingPendingFunctors_ 标识当前loop正在执行回调，此时loop又有了新的回调。
    if(!isInLoopThread() || callingPendingFunctors_)  // 这里的callingPendingFunctors_待解释
    {
        wakeup();// 唤醒loop所在线程
    }
}
// 用来唤醒loop所在的线程的 向wakeupfd写一个数据
void EventLoop::wakeup()
{
    uint64_t one = 1;
    ssize_t n = write(wakeupFd_,&one,sizeof one);
    if(n != sizeof one)
    {
        LOG_ERROR("EventLoop::wakeup() wirtes %lu bytes instead of 8\n",n);
    }
}

// EventLoop的方法 =》 Poller的方法
void EventLoop::updateChannel(Channel* channel)
{
    // poller_是父组件
    poller_->updateChannel(channel);
}
void EventLoop::removeChannel(Channel* channel)
{
    poller_->removeChannel(channel);
}
bool EventLoop::hasChannel(Channel* channel)
{
    return poller_->hasChannel(channel);
}

void EventLoop::handlerRead()
{
    uint64_t one = 1;
    ssize_t n = read(wakeupFd_, &one, sizeof one);
    if (n != sizeof one)
    {
        LOG_ERROR("EventLoop::handlerRead() reads %d bytes instead of 8", n);
    }
}

// 为了并发操作，定义局部的vector
 void EventLoop::doPendingFunctors()
 {
    std::vector<Functor> functors;
         = true;
    {
        std::unique_lock<std::mutex> lock(mutex_);
        functors.swap(pendingFunctors_);
    }
    // 上面是对效率的考量，主要是下面需要进行执行任务
    for(const Functor& functor:functors)
    {
        functor(); // 执行当前loop需要执行的回调操作
    }
    callingPendingFunctors_ = false;
 }